package wechat_api_remote

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"git.mycaigou.com/gfyx/common/http_client"
	"git.myscrm.cn/golang/stark/v4"
	"io"
	"net/http"
	"strings"
)

type wechatApiRepo struct{}

const (
	WechatHost = "https://api.weixin.qq.com"

	WechatMpAppidKey  = "gfyx_wechat_mp_appid"
	WechatMpSecretKey = "gfyx_wechat_mp_secret"

	GetTokenUri         = "/cgi-bin/token"
	JsCode2SessionUri   = "/sns/jscode2session"
	GetUserMobileUri    = "/wxa/business/getuserphonenumber"
	GetUnLimitQrCodeUri = "/wxa/getwxacodeunlimit"
)

func NewWechatApiRepository() WechatApiRepoIface {
	return &wechatApiRepo{}
}

func (r *wechatApiRepo) GetAccessToken(ctx context.Context) (*GetAccessTokenResponse, error) {
	var mpToken GetAccessTokenResponse
	wechatMpAppID := stark.Configer.(stark.ApolloConfigerIface).GetStringValue(WechatMpAppidKey, "")
	wechatMpSecret := stark.Configer.(stark.ApolloConfigerIface).GetStringValue(WechatMpSecretKey, "")
	url := fmt.Sprintf("%s%s?appid=%s&secret=%s&grant_type=client_credential",
		WechatHost, GetTokenUri, wechatMpAppID, wechatMpSecret)
	_, _, errs := http_client.New().Get(ctx, url, nil).EndStruct(&mpToken)
	if len(errs) > 0 {
		return nil, errs[0]
	}

	if mpToken.ErrCode != 0 {
		return nil, errors.New(mpToken.ErrMsg)
	}

	return &mpToken, nil
}

func (r *wechatApiRepo) JsCode2Session(ctx context.Context, code string) (*MPLoginInfo, error) {
	var mpLoginInfo MPLoginInfo
	wechatMpAppID := stark.Configer.(stark.ApolloConfigerIface).GetStringValue(WechatMpAppidKey, "")
	wechatMpSecret := stark.Configer.(stark.ApolloConfigerIface).GetStringValue(WechatMpSecretKey, "")
	url := fmt.Sprintf("%s%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
		WechatHost, JsCode2SessionUri, wechatMpAppID, wechatMpSecret, code)
	_, _, errs := http_client.New().Get(ctx, url, nil).EndStruct(&mpLoginInfo)
	if len(errs) > 0 {
		return nil, errs[0]
	}

	if mpLoginInfo.ErrCode != 0 {
		return nil, errors.New(mpLoginInfo.ErrMsg)
	}

	return &mpLoginInfo, nil
}

func (r *wechatApiRepo) GetMpMobile(ctx context.Context, accessToken, mobileCode string) (string, error) {
	url := fmt.Sprintf("%s%s?access_token=%s",
		WechatHost, GetUserMobileUri, accessToken)

	params := map[string]interface{}{
		"code": mobileCode,
	}

	mpPhone := &MpPhone{}
	_, _, errs := http_client.New().Post(ctx, url, params, nil).EndStruct(&mpPhone)
	if len(errs) > 0 {
		return "", errs[0]
	}

	if mpPhone.PhoneInfo != nil {
		return mpPhone.PhoneInfo.PhoneNumber, nil
	}

	return "", errors.New("获取微信手机号失败")
}

func (r *wechatApiRepo) GetUnLimitQrCode(ctx context.Context, request *GetWxUnLimitQrCodeRequest, accessToken string) ([]byte, error) {
	bts, _ := json.Marshal(request)
	url := fmt.Sprintf("%s%s?access_token=%s", WechatHost, GetUnLimitQrCodeUri, accessToken)
	response, err := http.Post(url, "application/json", bytes.NewReader(bts))
	stark.Logger.Infof(ctx, "GetUnLimitQrCode url:%s request:%s, response content-type:%s", url, string(bts), response.Header.Get("Content-Type"))
	//fmt.Printf("GetUnLimitQrCode request:%s, response content-type:%s\n", string(bts), response.Header.Get("Content-Type"))
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	respBody, err := io.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	switch headerContentType := response.Header.Get("Content-Type"); {
	case strings.HasPrefix(headerContentType, "application/json"):
		resp := &GetWxUnLimitQrCodeResponse{}
		err = json.Unmarshal(respBody, resp)
		if err != nil {
			return nil, err
		}
		return nil, errors.New(resp.ErrMsg)
	case strings.HasPrefix(headerContentType, "image"):
		return respBody, nil
	default:
		return nil, errors.New("获取二维码图片失败")
	}
}
